/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		test_mesh.cpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-03-03 16:26
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-04-17 12:39
*
*   Description:
*
=============================================================================*/
#define BOOST_TEST_MODULE test_mesh

#include "../include/fem.hpp"
#include "../include/implicit_solver.hpp"
#include "../include/incremental_load.hpp"
#include "../include/io/data_extractor.hpp"
#include "../include/io/vtu_writer.hpp"
#include "../include/model/model.hpp"
#include "../include/solid.hpp"
#include "../include/static_equation.hpp"
#include <boost/test/included/unit_test.hpp>

LOGGING_REGISTER()

BOOST_AUTO_TEST_CASE(test_mesh) {

  using namespace geoxfem;

  using MethodPolicy   = geoxfem::model::fem;
  using CouplePolicy   = geoxfem::model::solid;
  using DimensionType  = geoxfem::geometry::plane_stress;
  using EquationPolicy = geoxfem::model::static_equation;
  using SolvePolicy    = geoxfem::model::implicit_solver;
  using LoadPolicy     = geoxfem::model::incremental_load;
  using Model =
    geoxfem::model::Model<MethodPolicy, CouplePolicy, DimensionType,
                          EquationPolicy, SolvePolicy, LoadPolicy, mpl1>;

  std::string input_file_name =
    (boost::unit_test::framework::master_test_suite().argc < 2)
      ? "test/mesh_test.json"
      : boost::unit_test::framework::master_test_suite().argv[1];

  /*  detail, trace, process, info, warning, debug, error }; */
  geoxfem::log::log_init(geoxfem::log::severity_level::error);

  io::DataParser<io::json> parser;
  parser.read(input_file_name);

  /* io::DataExtractor<Model> extractor; */
  /* extractor.init(parser); */

  io::DataWriter<Model, io::vtu> writer;
  writer.init(parser.getPath(), parser.getFileName());

  /* io::DataPloter                 ploter; */

  Model model;
  /* model.append(extractor); */
  model.append(&writer);

  model.init(parser);
  model.buildProblem();

  BOOST_CHECK(model.getNumberOfShapes(0) == 9);
  BOOST_CHECK(model.getNumberOfShapes(1) == 12);
  BOOST_CHECK(model.getNumberOfShapes(2) == 4);

  BOOST_CHECK(model.getShape(0, 0)->getNumberOfNeighbors(1) == 2);
  BOOST_CHECK(model.getShape(0, 0)->getNumberOfNeighbors(2) == 1);

  BOOST_CHECK(model.getShape(0, 4)->getNumberOfNeighbors(0) == 3);
  BOOST_CHECK(model.getShape(0, 4)->getNumberOfNeighbors(1) == 3);
  BOOST_CHECK(model.getShape(0, 4)->getNumberOfNeighbors(2) == 2);

  BOOST_CHECK(model.getShape(0, 8)->getNumberOfNeighbors(0) == 4);
  BOOST_CHECK(model.getShape(0, 8)->getNumberOfNeighbors(1) == 4);
  BOOST_CHECK(model.getShape(0, 8)->getNumberOfNeighbors(2) == 4);

  {
    std::vector<size_t> list;
    for(auto& v : verticesIn(*model.getShape(0, 0)))
      list.emplace_back(v->getHeadPoint().getIndex());
    std::sort(list.begin(), list.end());
    BOOST_CHECK(list == std::vector<size_t>({4, 7}));
  }

  {
    std::vector<size_t> list;
    for(auto& v : verticesIn(*model.getShape(0, 4)))
      list.emplace_back(v->getHeadPoint().getIndex());
    std::sort(list.begin(), list.end());
    BOOST_CHECK(list == std::vector<size_t>({0, 1, 8}));
  }

  for(size_t i = 0; i != 4; ++i) {
    auto                shp = *model.getShape(2, i);
    std::vector<size_t> list1;
    for(auto& p : pointsIn(shp))
      list1.emplace_back(p.getIndex());
    list1.pop_back();
    std::vector<size_t> list2;
    for(auto& v : verticesIn(shp))
      list2.emplace_back(v->getIndex());
    BOOST_CHECK(list1 == list2);
    std::vector<size_t> list3;
  }

  BOOST_CHECK(model.getShape(0, 0)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 1)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 2)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 3)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 4)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 5)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 6)->ifBoundary());
  BOOST_CHECK(model.getShape(0, 7)->ifBoundary());
  BOOST_CHECK(!model.getShape(0, 8)->ifBoundary());

  BOOST_CHECK(model.getShape(1, 0)->ifBoundary());
  BOOST_CHECK(!model.getShape(1, 1)->ifBoundary());
  BOOST_CHECK(!model.getShape(1, 2)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 3)->ifBoundary());
  BOOST_CHECK(!model.getShape(1, 4)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 5)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 6)->ifBoundary());
  BOOST_CHECK(!model.getShape(1, 7)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 8)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 9)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 10)->ifBoundary());
  BOOST_CHECK(model.getShape(1, 11)->ifBoundary());

  BOOST_CHECK(model.getShape(2, 0)->ifBoundary());
  BOOST_CHECK(model.getShape(2, 1)->ifBoundary());
  BOOST_CHECK(model.getShape(2, 2)->ifBoundary());
  BOOST_CHECK(model.getShape(2, 3)->ifBoundary());
}
